import pandas as pd

from . import expert_strategy
import inspect

class UNION_Strategy(object):
    def __init__(self, weight=None):
        """
        ####################################################################################################
             function : 联合加权模型
             return   : None
             ----------------------------------------------------------------------------------------
             history :
             huangkunyang : create   '2025-06-24'      <519462724@qq.com>
        ####################################################################################################
        """
        self.expert_strategy_list = []
        for name, obj in inspect.getmembers(expert_strategy, inspect.isclass):
            if inspect.isclass(obj):
                self.expert_strategy_list.append(obj)
        # print(self.expert_strategy_list)
        if weight:
            if isinstance(weight, list):
                self.weight = weight
            else:
                raise TypeError("weight must be list")
        else:
            self.weight = [1] * len(self.expert_strategy_list)
        self.signals = pd.DataFrame()

    def update_weight(self):
        pass

    def show_weight(self):
        print("============= union model is lunched with weight =============")
        for i in range(len(self.expert_strategy_list)):
            print("%s --> %.2f" %(self.expert_strategy_list[i], self.weight[i]))
        print("")

    def update(self, df, thd=0.1):
        # print(df)
        # 遍历计算专家策略中所有策略的信号
        for strategy in self.expert_strategy_list:
            if strategy.__name__ == "BASIC_STRATEGY":
                continue
            temp_class = strategy()
            temp_sign_df = temp_class.update(df)
            self.signals[strategy.__name__ + "_Buy_Signal"] = temp_sign_df["Buy_Signal"].astype(bool).astype(int)
            self.signals[strategy.__name__ + "_Sell_Signal"] = temp_sign_df["Sell_Signal"].astype(bool).astype(int)
        # print(self.signals.astype(bool).astype(int))
        # 初始化信号及权重值
        total_weight = sum(self.weight)
        self.signals["Sell_Signal"] = 0
        self.signals["Buy_Signal"] = 0
        #
        for i in range(len(self.expert_strategy_list)*2):
            # 偶数为买信号
            if i % 2 == 1:
                weight = self.weight[i//2] / total_weight
                self.signals["Sell_Signal"] = self.signals["Sell_Signal"] + weight * self.signals.iloc[:, i]
            # 奇数为卖信号
            else:
                weight = self.weight[i//2] / total_weight
                self.signals["Buy_Signal"] = self.signals["Buy_Signal"] + weight * self.signals.iloc[:, i]
        # 数据处理 ----------------------------------------------------------------------------------------
        # 处理信号相同情况下
        self.signals["clear_equal_signal"] = (self.signals["Buy_Signal"] - self.signals["Sell_Signal"]).astype(bool).astype(int)
        self.signals["Buy_Signal"] = self.signals["Buy_Signal"] * self.signals["clear_equal_signal"]
        self.signals["Sell_Signal"] = self.signals["Sell_Signal"] * self.signals["clear_equal_signal"]
        # 清洗 买卖均有权重时的最终归属
        self.signals["clear_buy_signal"] = ((self.signals["Buy_Signal"] - self.signals["Sell_Signal"]) > thd).astype(int)
        self.signals["Buy_Signal"] = self.signals["Buy_Signal"] * self.signals["clear_buy_signal"]
        self.signals["clear_sell_signal"] = ((self.signals["Buy_Signal"] - self.signals["Sell_Signal"]) < -thd).astype(int)
        self.signals["Sell_Signal"] = self.signals["Sell_Signal"] * self.signals["clear_sell_signal"]
        # 数据预处理 ----------------------------------------------------------------------------------------
        # print(self.signals[~(self.signals["Buy_Signal"] == 0) | ~(self.signals["Sell_Signal"] == 0)][["Buy_Signal", "Sell_Signal"]])
        self.signals = self.signals.astype(bool).astype(int)
        # print(self.signals[~(self.signals["Buy_Signal"] == 0) | ~(self.signals["Sell_Signal"] == 0)][["Buy_Signal", "Sell_Signal"]])
        return self.signals

if __name__ == '__main__':
    for name, obj in inspect.getmembers(expert_strategy, inspect.isclass):
        if inspect.isclass(obj):
            print(name)

